package com.mapler.service;

import com.mapler.model.AdModel;
import com.mapler.model.SModel;
import com.mapler.model.UAModel;
import com.mapler.utility.Util;
import com.mapler.utility.W4MUtil;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Random;
import org.apache.log4j.Logger;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

/**
 *
 * @author none
 */
public class W4MClick implements Runnable {

    private SModel sModel;
    private ArrayList<UAModel> uaModels;
    ArrayList<AdModel> addModels;
    private Random random;
    private HashMap<String, UAModel> usHashMap;
    private static Logger log = Logger.getLogger(W4MClick.class);
    private INotifier iNotifier;
    private ArrayList<AdModel> useAdModel = new ArrayList<AdModel>();
    WebDriver driver = null;
    private Integer postInSession = 0;
    private HashMap<Integer, ArrayList<AdModel>> addMap = new HashMap();
    private int globalWhichSlot;

    public W4MClick(INotifier iNotifier, SModel sModel, ArrayList<UAModel> uaModels, ArrayList<AdModel> addModels,
            HashMap<String, UAModel> usHashMap) {
        this.sModel = sModel;
        this.uaModels = uaModels;
        this.addModels = addModels;
        this.usHashMap = usHashMap;
        this.iNotifier = iNotifier;
    }

    public W4MClick(SModel iModel) {
        this.sModel = iModel;
    }

    public Random getRandom() {
        if (random == null) {
            random = new Random();
        }
        return random;
    }

    public void setRandom(Random random) {
        this.random = random;
    }

    @Override
    public void run() {
        try {
            if (sModel.isIsVPN()) {
                log.debug("W4M:Run::Going to run for VPN");
                this.init();
                log.debug("W4M:Run::Done !!!");
            } else {
                log.debug("W4M:Run::Going to run for SOCKS");
                this.init();
                log.debug("W4M:Run::Done !!!");
            }
        } catch (Throwable ex) {
            iNotifier.notify("W4M:Run:: stopped for error: " + ex.getMessage());
            log.error("W4M:Run:: stopped causes " + ex);
        }
    }
    int postlimit = 0;

    private void init() {
        /* if global / run indvidual set then dont need to check that */
        postlimit = Integer.parseInt(sModel.getPostPerIP());
        useAdModel.addAll(addModels);
        int addMapSize = this.getAddMap().size();
        if (addMapSize != postlimit && !sModel.isRunIndividually()) {
            iNotifier.notify("W4M:: Slot is defined incorrectly. Slot defined " + addMapSize + " but required " + postlimit);
            return;
        }
        for (UAModel uam : uaModels) {
            try {
                if (sModel.isStopEngine()) {
                    break;
                }
                if (sModel.getChangeIP().equals("1")) {
                    if (uam.getProxy().isEmpty() || sModel.getName().isEmpty() || sModel.getPass().isEmpty()) {
                        iNotifier.notify("W4M:: proxy, username or password is empty. Goitng to try for another account");
                        log.debug("W4M:goVPN:: proxy, username or password is empty. Going to try for another account");
                        continue;
                    }

                    iNotifier.notify("W4M:: Going to connect VPN for " + uam.getProxy());
                    boolean connect = Util.connect(uam.getProxy(), sModel.getName(), sModel.getPass());
                    if (!connect) {
                        iNotifier.notify("W4M:: unable to connect VPN.");
                        log.debug("W4M:goVPN:: unable to connect for " + uam.getProxy());
                        if (sModel.isUpdateAccount()) {
                            Util.updateWorking(sModel, uam.getId(), 2);
                        }
                        continue;
                    }
                }
                if (sModel.isUpdateAccount()) {
                    Util.updateWorking(sModel, uam.getId(), 2);
                }

                iNotifier.notify("W4M:: Going to posting for " + uam.getProxy());
                log.debug("W4M:goVPN:: going to posting for " + uam.getProxy());
                sModel.setPostCount(0);
                for (int i = 1; i <= postlimit; i++) {
                    iNotifier.notify("W4M:: going to posting for " + i);
                    sModel.setTryCount(1);
                    this.doPost(uam, i);
                    iNotifier.notify("W4M:: posting done " + i);
                    log.debug("W4M:goVPN:: posting done " + i);

                    iNotifier.notify("W4M:: Waiting for before another post.");
                    Util.wait(Integer.parseInt(sModel.getPostInterval()));
                }

                iNotifier.notify("W4M:: end of posting for " + uam.getProxy());
                log.debug("W4M:goVPN:: end of posting for " + uam.getProxy());
                if (sModel.getChangeIP().equals("1")) {
                    boolean disconnect = Util.disConnect(uam.getProxy(), sModel.getName(), sModel.getPass());
                    if (!disconnect) {
                        iNotifier.notify("W4M:: unable to disconnec VPN ");
                        log.debug("W4M:goVPN:: unable to disconnect VPN(no more further action) for " + uam.getProxy());
                        break;
                    } else {
                        iNotifier.notify("W4M:: disconnected from VPN ");
                        log.debug("W4M:goVPN:: disconnected form VPN ");
                    }
                }
            } catch (Throwable ex) {
                iNotifier.notify("W4M::Error on posting. Going to try for another account");
                log.debug("W4M::Error on posting. Going to try for another account" + ex);
            }
        }
        iNotifier.notify("Signup:: Finished work !!! ");
        log.debug("Signup:: Finished work !!! ");
    }
    private boolean createDriver = true;

    private void doPost(UAModel uam, Integer whichSlot) {
        try {
            AdModel adModel = new AdModel();

            /* slot checking here. if use slot then use that */
            if (sModel.isUseSlot()) {
                addModels.clear();

                /* if run individual is define then ignore slot here and use global slot */
                if (this.getGlobalWhichSlot() == 0) {
                    /* if slot no assigned then use that one as slot one */
                    if (sModel.getSlotNo() > 0) {
                        whichSlot = sModel.getSlotNo();
                    }
                } else {
                    whichSlot = globalWhichSlot;
                }
                addModels.addAll(this.getAddMap().get(whichSlot));
                useAdModel = addModels;
            }

            /*check add null or empty here. if that then pull from orginal and fill into temp*/
            if (useAdModel == null || useAdModel.isEmpty() || useAdModel.size() == 1) {
                if (sModel.isUseSlot()) {
                    addModels.addAll(this.getAddMap().get(whichSlot));
                    useAdModel = addModels;
                } else {
                    useAdModel.addAll(addModels);
                }
            }

            /* if still null then brek that */
            if (useAdModel == null || useAdModel.isEmpty() || useAdModel.size() == 1) {
                iNotifier.notify("W4M:: Got ad empty.");
                log.debug("W4M:doPost:: Got ad empty.");
                throw new Exception("W4M:doPost:: Got ad empty.");
            }

            int indx = 0;
            if (sModel.isRandom()) {
                indx = this.getRandom().nextInt(useAdModel.size());
            }
            adModel = useAdModel.get(indx);
            useAdModel.remove(indx);

            /*if (true) {
             System.out.println("Account=" + uam.getEmail() + ", Slot = " + whichSlot + ", ADD =" + adModel.getTitle());
             return;
             }*/
            /* if post is not session then always create new driver for each post*/
            if (!sModel.isPostInSession() || createDriver) {
                driver = Util.createDriver(sModel, uam);
                createDriver = false;
            }

            if (driver == null) {
                iNotifier.notify("W4M:: unable to init driver. driver is null");
                log.debug("W4M:doPost:: driver is null. Unable to init driver");
                throw new Exception("W4M:doPost:: driver is null. Unable to init driver");
            }

            iNotifier.notify("W4M:: Working for account :" + uam.getProxy() + " Email :" + uam.getEmail() + ", Please wait ...");

            List<WebElement> elements;
            if (sModel.getLogincl().equals("1")) {
                if (!sModel.isPostInSession() || (sModel.isPostInSession() && sModel.getPostCount() == 0)) {
                    driver.get("https://accounts.craigslist.org/");
                    WebElement email = driver.findElement(By.id("inputEmailHandle"));
                    email.sendKeys(uam.getEmail());

                    WebElement pass = driver.findElement(By.id("inputPassword"));
                    pass.sendKeys(uam.getClientPassword());

                    /* Click on login submit button */
                    Util.byButton(driver, "button", "type", "submit");
                }
            }

            driver.get(uam.getLink());
            if (!uam.getLink().contains("=")) {
                Util.byClickTag(driver, "post");

                Util.wait(3);
                driver.findElement(By.xpath("//input[@value='p']")).click();

                Util.wait(2);
                driver.findElement(By.xpath("//input[@value='cas']")).click();
            }

            driver.findElement(By.xpath("//input[@id='w']")).click();
            driver.findElement(By.xpath("//input[@id='m2']")).click();

            /* Click on continue button */
            Util.byButton(driver, "button", "value", "Continue");

            /* section for location selection */
            ArrayList<WebElement> webElements = new ArrayList<WebElement>();
            elements = driver.findElements(By.tagName("input"));
            for (WebElement elementLink : elements) {
                if (elementLink.getAttribute("type") != null
                        && elementLink.getAttribute("type").equalsIgnoreCase(
                        "radio")) {
                    webElements.add(elementLink);
                }
            }

            if (!webElements.isEmpty()) {
                int index = this.getRandom().nextInt(webElements.size());
                webElements.get(index).click();
            }

            /* section for click on bypass this step */
            try {
                elements = driver.findElements(By.tagName("input"));
                for (WebElement elementLink : elements) {
                    if ((elementLink.getAttribute("type") != null
                            && elementLink.getAttribute("type").equalsIgnoreCase(
                            "radio")) && (elementLink.getAttribute("value") != null
                            && elementLink.getAttribute("value").equalsIgnoreCase(
                            "0"))) {
                        elementLink.click();
                        break;
                    }
                }
            } catch (Throwable ex) {
                log.error("Bypass this step:" + ex.getMessage());
            }

            // Location parse.
            Util.wait(1);
            String location;
            WebElement ele = driver.findElement(By.xpath("//section[@class='contents']"));
            String postLocation = "";
            if (!sModel.getLogincl().equals("1")) {
                // reply to and confirm reply to email set if not login
                WebElement element = driver.findElement(By.id("FromEMail"));
                element.clear();
                element.sendKeys(uam.getEmail());

                element = driver.findElement(By.id("ConfirmEMail"));
                element.clear();
                element.sendKeys(uam.getEmail());

                postLocation = ele.getText().trim().replace("log in to your account", "").replace("(Apply for Account)", "").trim();
                String[] postLocations = postLocation.split(">");
                if (postLocations.length == 4) {
                    location = postLocations[0].replace("craigslist", "").trim();
                } else {
                    location = postLocations[1].trim();
                }
            } else {
                postLocation = ele.getText().trim().substring(ele.getText().trim().indexOf("logout")).replace("logout ]", "").trim();
                String[] postLocations = postLocation.split(">");
                if (postLocations.length == 4) {
                    location = postLocations[0].replace("craigslist", "").trim();
                } else {
                    location = postLocations[1].trim();
                }
            }

            String postTitle = adModel.getTitle();
            if (sModel.getPrefix() != null && !sModel.getPrefix().isEmpty()) {
                postTitle = sModel.getPrefix() + " " + postTitle;
            }

            if (sModel.getPostfix() != null && !sModel.getPostfix().isEmpty()) {
                postTitle = postTitle + " " + sModel.getPostfix();
            }

            String postLoc = Character.toUpperCase(location.charAt(0)) + location.substring(1);
            String postDesc = adModel.getDescription();



            driver.findElement(By.id("PostingTitle")).sendKeys(postTitle);

            if (sModel.getUseLocation().equals("1")) {
                driver.findElement(By.id("GeographicArea")).sendKeys(postLoc);
            }

            driver.findElement(By.id("PostingBody")).sendKeys(postDesc);

            if (sModel.getUseAge().equals("1")) {
                int postAge;
                if (adModel.getAge() != null && !adModel.getAge().isEmpty()) {
                    postAge = Integer.parseInt(adModel.getAge());
                } else {
                    int max = 50;
                    int min = 17;
                    if (sModel.getUpage() != null) {
                        max = Integer.parseInt(sModel.getUpage());
                    }
                    if (sModel.getLwage() != null) {
                        min = Integer.parseInt(sModel.getLwage());
                    }
                    postAge = this.getRandom().nextInt(max - min + 1) + min;
                }
                driver.findElement(By.id("Ask")).sendKeys("" + postAge);
            }

            if (adModel.getBody() != null && !adModel.getBody().isEmpty()) {
                Util.sendKeysById(driver, "pers_body_type_is", adModel.getBody().trim());
            }

            if (adModel.getHeight() != null && !adModel.getHeight().isEmpty()) {
                Util.sendKeysById(driver, "pers_height_is", adModel.getHeight().trim());
            }

            if (adModel.getStatus() != null && !adModel.getStatus().isEmpty()) {
                Util.sendKeysById(driver, "pers_relationship_status_is", adModel.getStatus().trim());
            }

            /* Click continue button for submit post */
            Util.byButton(driver, "button", "value", "Continue");

            /* Click done with image button for go next step */
            Util.byButton(driver, "button", "value", "Done with Images");

            /* click continue button on final preview page */
            Util.byButton(driver, "button", "value", "Continue");

            /* Your posting check and update into server */
            Util.wait(3);
            boolean emcReq = true;
            elements = driver.findElements(By.tagName("li"));
            for (WebElement pelement : elements) {
                if (pelement.getText().contains("Your posting can be seen at") || pelement.getText().contains("View your post at")) {
                    elements = pelement.findElements(By.tagName("a"));
                    for (WebElement elementLink : elements) {
                        if (elementLink.getText().contains("craigslist.org")) {
                            emcReq = false;
                            Util.addPostInfo(iNotifier, sModel, elementLink.getText());
                            break;
                        }
                    }
                    break;
                }
            }

            if (sModel.isDeletePost()) {
                Util.deleteAdd(sModel, adModel, iNotifier);
            }

            if (emcReq) {
                iNotifier.notify("W4M: going to check email.");
                for (int i = 1; i <= sModel.getEmailReadTry(); i++) {
                    MailRunner mailRunner = new MailRunner(iNotifier, sModel, uam, adModel);
                    mailRunner.checkEmail(driver);
                    if(uam.isMailFound()){
                        break;
                    }
                }
            }
        } catch (Throwable ex) {
            iNotifier.notify("W4M: Stopped for error: " + ex.getMessage());
            log.error("W4M:doPost:: Stopped causes..." + ex);
            if (sModel.getTryCount() <= Integer.parseInt(sModel.getMaxTry())) {
                iNotifier.notify("W4M: Going to post again for failed. fail count " + sModel.getTryCount());
                if (driver != null) {
                    if (sModel.isCloseBrowser() && !sModel.isPostInSession()) {
                        driver.quit();
                    }
                }
                sModel.setTryCount(sModel.getTryCount() + 1);
                this.doPost(uam, whichSlot);
            }
        } finally {
            /* count post */
            sModel.setPostCount(sModel.getPostCount() + 1);
            if (postlimit == sModel.getPostCount()) {
                /* After post per ip done go for renew link */
                if (sModel.getRenewItems() != null && !sModel.getRenewItems().isEmpty()) {
                    iNotifier.notify("Going to click on renew link and click...!");
                    W4MUtil.clickReNewLink(driver, sModel, iNotifier);
                }

                /* If post in same then make create driver true here its means it will quit old one and create new one */
                if (sModel.isPostInSession()) {
                    createDriver = true;
                }
            }
            /* if post is not same means browser need to close and create for each post */
            if (!sModel.isPostInSession() || createDriver) {
                if (sModel.isCloseBrowser()) {
                    Util.quitDriver(driver);
                }
            }
        }
    }

    public HashMap<Integer, ArrayList<AdModel>> getAddMap() {
        return addMap;
    }

    public void setAddMap(HashMap<Integer, ArrayList<AdModel>> addMap) {
        this.addMap = addMap;
    }

    public int getGlobalWhichSlot() {
        return globalWhichSlot;
    }

    public void setGlobalWhichSlot(int globalWhichSlot) {
        this.globalWhichSlot = globalWhichSlot;
    }

    public static void main(String s[]) {
        try {
            /*String d = "2013-09-26 23:56:09";
             SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd hh:mm");
             System.out.println(formatter.format(formatter.parse(d)));

             SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm aa");
             String formattedDate = dateFormat.format(formatter.parse(d)).toString();
             System.out.println(formattedDate);
             */
            SModel sModel = new SModel();
            //sModel.setDriver("Safari");
            //sModel.setDriver("GC");
            sModel.setUseSystem(true);
            //sModel.setProxyServer("172.25.100.80");
            //sModel.setProxyPort(8080);
            //sModel.setProxyType(true);
            //sModel.setBrowserProxy(true);
            //sModel.setDriver("IE");
            sModel.setDriver("FF");
            //sModel.setDriver("GC");

            //sModel.setSafariPath("F:\\tools\\Safari\\Safari.exe");
            //sModel.setSafariPath("F:\\tools\\Safari\\Safari.exe");
            //sModel.setSafariPath("F:\\tools\\Opera\\opera.exe");
            //sModel.setIePath("D:\\driver\\IE\\IEDriverServer.exe");
            sModel.setLink("https://post.craigslist.org/k/YK60ZnVm5BGBskUjNcTI0w/Shyhn?s=mix");

            WebDriver driver = Util.createDriver(sModel, new UAModel());
            WebDriverWait wait = new WebDriverWait(driver, 17);
            driver.get(sModel.getLink());

            WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//input[@id='w']")));
            element.click();

            element = wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//input[@id='m2']")));
            element.click();

            /* Click on continue button */
            Util.byButton(driver, "button", "value", "Continue");

            element = wait.until(ExpectedConditions.elementToBeClickable(By.id("FromEMail")));
            element.click();
            element.clear();
            element.sendKeys("imtestemail@yahoo.com");

            element = wait.until(ExpectedConditions.elementToBeClickable(By.id("ConfirmEMail")));
            element.click();
            element.clear();
            element.sendKeys("imtestemail passowrd");

            Util.wait(27);
            driver.quit();
        } catch (Throwable ex) {
            ex.printStackTrace();
        }
    }
}
